package org.mbds.android.sismapp;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.json.JSONException;
import org.json.JSONObject;
import org.mbds.android.location.GPSTools;
import org.mbds.android.p2p.services.P2pService;
import org.mbds.android.p2p.services.P2pServiceMessageHandler;
import org.mbds.android.sismapp.activity.SensorDataCollectorActivity;
import org.mbds.android.sismapp.network.SismappNetworkTools;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;

public class SismappMessage {
	public final static String JSON_ATTRIBUTE_FIRSTNAME = "";
	public final static String JSON_ATTRIBUTE_LASTNAME = "";
	public final static String JSON_ATTRIBUTE_LATITUDE = "";
	public final static String JSON_ATTRIBUTE_LONGITUDE = "";
	public final static String JSON_ATTRIBUTE_TIMESTAMP = "";
	public final static String JSON_ATTRIBUTE_MESSAGE = "";
	public final static String JSON_ATTRIBUTE_IP = "";
	
	public final static String MESSAGE_USER_SISMAPP_CONNECTED = "USER_SISMAPP_CONNECTED";
	public final static String MESSAGE_DYFI = "DYFI";
	public final static String MESSAGE_SEISMIC_ALERT_CONFIRMED = "SEISMIC_ALERT_CONFIRMED";
	public final static String MESSAGE_SEND_MSG_TO_SISMAPP_NETWORK = "SEND_MSG_TO_SISMAPP_NETWORK";

	public final static SimpleDateFormat s = new SimpleDateFormat("ddMMyyyyhhmmss");

	private SismappUser sender;
	private String timestamp;
	private String message;
	private JSONObject formattedMessage;
	
	/**
	 * This method is called to send message on SISMAPP P�P network
	 * @param message
	 * @return
	 * @throws Exception
	 */
	public static boolean sendSismappMessage(String message) throws Exception {
		
		if (message==null || 
				(message!=MESSAGE_DYFI && message!=MESSAGE_SEISMIC_ALERT_CONFIRMED))
			throw new Exception("Unknown SISMAPP message");
		if (message==MESSAGE_DYFI)
			SismappStaticCommons.setSeismicAlertLevel(SismappStaticCommons.SEISMIC_ALERT_LEVEL_SENSORS_LOCAL_DETECTION);
		else if (message==MESSAGE_SEISMIC_ALERT_CONFIRMED)
			SismappStaticCommons.setSeismicAlertLevel(SismappStaticCommons.SEISMIC_ALERT_LEVEL_USER_CONFIRMED);
		SismappUser user = new SismappUser(SismappNetworkTools.getDottedDecimalIP(),
				SismappStaticCommons.getFirstName(), 
					SismappStaticCommons.getLastName(), GPSTools.getLastKnownPosition());
		SismappMessage msg = new SismappMessage(user, message);
		String messageToSend = msg.getFormattedMessage().toString();
		//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		// => Ajouter le lien avec la communication P2P ICI 
		//    et renvoyer le booleen
		//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		
		Message mess = Message.obtain(null, P2pService.TYPE_SEND_MESSAGE);
		mess.obj = messageToSend;
		SensorDataCollectorActivity.p2pServiceInterface.send(mess);
		return false;
	}
	
	
	
	/**
	 * This method must be called by P2P service 
	 * when a message is received from SISMAPP network
	 * @param jsonStringMessage
	 * @return
	 * @throws Exception
	 */
	
	public static void receiveSismappMessage(String jsonStringMessage)throws Exception {
		//SismappMenu.alert(SismappApplication.getAppContext());
		SismappMessage msg = null;
		try {
			JSONObject o = new JSONObject(jsonStringMessage);
			msg = new SismappMessage(o);
		} catch (Exception e) {
			throw e;
		}
		
		// Update list of SISMAPP users on network
		SismappStaticCommons.updateNetworkUsers(msg.getSender());
		
		if (msg.isDyfiMessage() && SismappStaticCommons.getSeismicAlertLevel()
				==SismappStaticCommons.SEISMIC_ALERT_LEVEL_SENSORS_LOCAL_DETECTION) {
			SismappStaticCommons.setSeismicAlertLevel(SismappStaticCommons.SEISMIC_ALERT_LEVEL_SENSORS_NETWORK_DETECTION);
			// alert sensors detection: ask user confirmation
			SismappMenu.alert(SismappApplication.getAppContext());
		} else if (msg.isSeismicAlertConfirmedMessage()) {
			SismappStaticCommons.setSeismicAlertLevel(SismappStaticCommons.SEISMIC_ALERT_LEVEL_USER_CONFIRMED);
			// earthquake confirmed
			SismappMenu.alert(SismappApplication.getAppContext());
		} else if (msg.isUserSismappConnectedMessage()) {
			sendSismappMessage(MESSAGE_USER_SISMAPP_CONNECTED);
		}
		
	}
	public SismappMessage(JSONObject formattedMessage) {
		this.formattedMessage = formattedMessage;
		String firstname = formattedMessage.optString(JSON_ATTRIBUTE_FIRSTNAME, "");
		String lastname = formattedMessage.optString(JSON_ATTRIBUTE_FIRSTNAME, "");
		double lat = formattedMessage.optDouble(JSON_ATTRIBUTE_LATITUDE, 0d);
		double lon = formattedMessage.optDouble(JSON_ATTRIBUTE_LONGITUDE, 0d);
		String ipAddr = formattedMessage.optString(JSON_ATTRIBUTE_IP, null);
		sender = new SismappUser(ipAddr, lastname, firstname, lat, lon);
		setTimestamp(formattedMessage.optString(JSON_ATTRIBUTE_FIRSTNAME, ""));
		message = formattedMessage.optString(JSON_ATTRIBUTE_MESSAGE, "");
	}
	
	public SismappMessage(SismappUser user, String message) throws JSONException {
		setMessage(message);
		setSender(user);
		setTimestamp(s.format(new Date()));
		formattedMessage = new JSONObject();
		formattedMessage.put(JSON_ATTRIBUTE_FIRSTNAME, getSender().getFirstName());
		formattedMessage.put(JSON_ATTRIBUTE_LASTNAME, getSender().getLastName());
		formattedMessage.put(JSON_ATTRIBUTE_LATITUDE, getSender().getLocation().getLatitude());
		formattedMessage.put(JSON_ATTRIBUTE_LONGITUDE, getSender().getLocation().getLongitude());
		formattedMessage.put(JSON_ATTRIBUTE_MESSAGE, getMessage());
		formattedMessage.put(JSON_ATTRIBUTE_TIMESTAMP, getTimestamp());
		formattedMessage.put(JSON_ATTRIBUTE_IP, getSender().getIpAddress());
	}

	public SismappUser getSender() {
		return sender;
	}

	private void setSender(SismappUser sender) {
		this.sender = sender;
	}

	public String getTimestamp() {
		return timestamp;
	}

	private void setTimestamp(String timestamp) {
		this.timestamp = timestamp;
	}

	public String getMessage() {
		return message;
	}

	private void setMessage(String message) {
		this.message = message;
	}

	public JSONObject getFormattedMessage() {
		return formattedMessage;
	}

	public boolean isDyfiMessage() {
		return (message.trim().equalsIgnoreCase(MESSAGE_DYFI));
	}
	public boolean isSeismicAlertConfirmedMessage() {
		return (message.trim().equalsIgnoreCase(MESSAGE_SEISMIC_ALERT_CONFIRMED));
	}
	public boolean isUserSismappConnectedMessage() {
		return (message.trim().equalsIgnoreCase(MESSAGE_USER_SISMAPP_CONNECTED));
	}
}
